package walls.utils;

import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.SignatureException;
import io.jsonwebtoken.security.WeakKeyException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import walls.exception.AuthException;

import javax.crypto.SecretKey;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Component
public class JwtTokenUtil {

    @Value("${jwt.secret}")
    private  String SECRET_KEY ;

    @Value("${jwt.expiration}")
    private  long EXPIRATION_TIME ; // 24小时（毫秒）

    @Value("${jwt.issuer}")
    private  String ISSUER ;


    // 安全地获取密钥（自动处理长度问题）
    private  SecretKey getSecretKey() {
        byte[] keyBytes = Decoders.BASE64.decode(SECRET_KEY);

        // 验证密钥长度
        if (keyBytes.length * 8 < 512) {
            throw new WeakKeyException("密钥长度不足512位。当前长度: " + (keyBytes.length * 8) + "位");
        }

        return Keys.hmacShaKeyFor(keyBytes);
    }

    /**
     * 生成JWT令牌
     *
     * @param userId 用户ID
     * @param username 用户名
     * @param roles 用户角色列表（逗号分隔）
     * @return JWT令牌字符串
     */
    public  String generateToken(Long userId, String username, String roles) {
        Date now = new Date();
        Date expiryDate = new Date(now.getTime() + EXPIRATION_TIME);

        // 创建自定义声明
        Map<String, Object> claims = new HashMap<>();
        claims.put("userId", userId);
        claims.put("username", username);
        claims.put("roles", roles);

        return Jwts.builder()
                .claims(claims)
                .issuer(ISSUER)
                .issuedAt(now)
                .expiration(expiryDate)
                .signWith(getSecretKey(), Jwts.SIG.HS512)
                .compact();
    }

    /**
     * 从令牌中获取声明
     *
     * @param token JWT令牌
     * @return 声明对象
     */
    public  Claims getClaimsFromToken(String token) {
        return Jwts.parser()
                .verifyWith(getSecretKey())
                .build()
                .parseSignedClaims(token)
                .getPayload();
    }

    /**
     * 从令牌中获取用户ID
     *
     * @param token JWT令牌
     * @return 用户ID
     */
    public  Long getUserIdFromToken(String token) {
        return getClaimsFromToken(token).get("userId", Long.class);
    }

    /**
     * 从令牌中获取用户名
     *
     * @param token JWT令牌
     * @return 用户名
     */
    public  String getUsernameFromToken(String token) {
        return getClaimsFromToken(token).get("username", String.class);
    }

    /**
     * 从令牌中获取角色列表
     *
     * @param token JWT令牌
     * @return 角色列表（逗号分隔）
     */
    public  String getRolesFromToken(String token) {
        return getClaimsFromToken(token).get("roles", String.class);
    }

    /**
     * 验证JWT令牌
     *
     * @param token JWT令牌
     * @return 验证结果
     */
    public  boolean validateToken(String token) {
        try {
            getClaimsFromToken(token);
            return true;
        } catch (SignatureException ex) {
//            System.err.println("无效的JWT签名: " + ex.getMessage());
            throw new AuthException("无效的JWT签名"+ ex.getMessage());
        } catch (MalformedJwtException ex) {
//            System.err.println("无效的JWT令牌: " + ex.getMessage());
            throw new AuthException("无效的JWT令牌"+ ex.getMessage());

        } catch (ExpiredJwtException ex) {
//            System.err.println("JWT令牌已过期: " + ex.getMessage());
            throw new AuthException("JWT令牌已过期"+ ex.getMessage());

        } catch (UnsupportedJwtException ex) {
//            System.err.println("不支持的JWT令牌: " + ex.getMessage());
            throw new AuthException("不支持的JWT令牌"+ ex.getMessage());

        } catch (IllegalArgumentException ex) {
//            System.err.println("JWT声明字符串为空: " + ex.getMessage());
            throw new AuthException("JWT声明字符串为空"+ ex.getMessage());

        } catch (JwtException ex) {
//            System.err.println("JWT处理错误: " + ex.getMessage());
            throw new AuthException("JWT处理错误"+ ex.getMessage());

        }
//        return false;
    }

    /**
     * 刷新令牌（延长有效期）
     *
     * @param token 原始令牌
     * @return 新令牌
     */
    public  String refreshToken(String token) {
        Claims claims = getClaimsFromToken(token);
        return generateToken(
                claims.get("userId", Long.class),
                claims.get("username", String.class),
                claims.get("roles", String.class)
        );
    }


}